package org.reliablesource.prism.ui.workbench.views;

/**
 *
 *  Copyright (c) 2006, Reliable Source, Inc. All Rights Reserved
 *
 *	Created on: Mar 27, 2006
 *	@author Dennis Park <a href="mailto:dennis.park@gmail.com">dennis.park@gmail.com</a>
 *
 */

import java.util.Observable;
import java.util.Observer;

import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.part.ViewPart;
import org.reliablesource.prism.core.IPrismElement;
import org.reliablesource.prism.core.IPrismScreen;
import org.reliablesource.prism.core.IPrismUpdateEvent;
import org.reliablesource.prism.core.plugin.PrismCorePlugin;
import org.reliablesource.prism.ui.composite.ViewMediator;
import org.reliablesource.prism.ui.plugin.PrismPlugin;
import org.reliablesource.prism.ui.viewers.PrismElementLabelProvider;
import org.reliablesource.prism.ui.viewers.PrismElementTreeContentProvider;

public class NavigatorViewPart extends ViewPart implements Observer{

	public final static String VIEW_ID = "org.reliablesource.prism.ui.workbench.views.navigatorview";
	
	private TreeViewer viewer;

	public NavigatorViewPart() {
		super();
	}

	public void createPartControl(final Composite parent) {
		viewer = new TreeViewer(parent, SWT.MULTI);
		viewer.setContentProvider(new PrismElementTreeContentProvider());
		viewer.setLabelProvider(new PrismElementLabelProvider());
		viewer.setInput(PrismCorePlugin.getDefault().getModel());

		
		viewer.addOpenListener(new IOpenListener() {
			public void open(OpenEvent event) {
				if (((StructuredSelection) viewer.getSelection())
						.getFirstElement() instanceof IPrismScreen)
					ViewMediator.getInstance().openImage(
							(IPrismScreen) ((StructuredSelection) viewer
									.getSelection()).getFirstElement());
			}
		});
		
		getSite().setSelectionProvider(viewer);
//		viewer.addSelectionChangedListener(new ISelectionChangedListener() {
//
//			public void selectionChanged(SelectionChangedEvent event) {
//				if(((StructuredSelection) (event.getSelection())).getFirstElement().equals(currentSelection))
//					return;
//				currentSelection = (IPrismElement) ((StructuredSelection) (event.getSelection())).getFirstElement();
//				firePropertyChange(PROP_TITLE);
//				Object o = Platform.getAdapterManager().getAdapter(((StructuredSelection) (event.getSelection())).getFirstElement(), IPropertySource.class);				
//			}
//
//		});

		
		// FIXME:  Delegate this logic (the actual update, and adding of 
		//			observer) to a nested composite. Decouple observer 
		// 			update logic from this ViewPart
		((Observable)PrismCorePlugin.getDefault().getModel()).addObserver(this);

		//	Contribute a menu to this ViewPart that will contain actions
		//		that are statically available for only this ViewPart. 
		createContextMenu();

		PrismPlugin.getDefault().addWidget(VIEW_ID+".contentTree", viewer.getControl());
		PrismPlugin.getDefault().addWidget(VIEW_ID, parent);
		
		PrismPlugin.getDefault().dumpCompositeContextMap();
		
	}

	public void setFocus() {
		if (viewer != null)
			viewer.getControl().setFocus();
	}

	
	/**
	 * This update is a call back or 'hook' method invoked by the model's
	 *	invocation of the notifyObservers() method.
	 */
	public void update(Observable arg0, final Object updateObject) {
		Display.getDefault().asyncExec(new Runnable(){
			public void run(){
				IPrismUpdateEvent updateEvent = ((IPrismUpdateEvent) updateObject);
				int _nObjs = updateEvent.getChangedObjects().length;
				for (int i = 0; i < _nObjs; i++) {
					IPrismElement _updated = updateEvent.getChangedObjects()[i];
					switch (updateEvent.getEventType()) {
					case IPrismUpdateEvent.REMOVE:
						viewer.remove(_updated);
						break;
					case IPrismUpdateEvent.UPDATE:
						viewer.update(_updated, null);
						break;
					case IPrismUpdateEvent.ADD:
						viewer.add(_updated.getParent(), _updated);
						break;
					}
				}
				viewer.refresh();
			}
			
		});
		// FIXME: This logic belongs in the content provider
	}

	void createContextMenu() {
		MenuManager menuManager = new MenuManager();
		menuManager.setRemoveAllWhenShown(true);
		
		Menu menu = menuManager.createContextMenu(viewer.getControl());
		viewer.getControl().setMenu(menu);
		getSite().registerContextMenu(menuManager, viewer);
		
		menuManager.addMenuListener(new IMenuListener() {
			public void menuAboutToShow(IMenuManager manager) {
				fillContextMenu(manager);
			}
		});

		
	}

	void fillContextMenu(final IMenuManager _mgr) {
		_mgr.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
	}
}